package me.hl.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 计数信号量
 * 一个计数信号量。从概念上讲，信号量维护了一个许可集合。如有必要，在许可可用前会阻塞每一个 acquire()，
 * 然后再获取该许可。每个 release() 添加一个许可，从而可能释放一个正在阻塞的获取者。但是，不使用实际的
 * 许可对象，Semaphore 只对可用许可的号码进行计数，并采取相应的行动。Semaphore 通常用于限制可以访
 * 问某些资源（物理或逻辑的）的线程数目
 * Created by Planck on 2016/1/29.
 */
public class SemaphoreTest implements Runnable {

    Semaphore position;
    private int num;

    public SemaphoreTest(int num, Semaphore position) {
        this.num = num;
        this.position = position;
    }

    public void run() {
        try {
            Integer release = position.availablePermits();

            if (release > 0) {
                System.out.println("目前有" + release + "个空位,欢迎第" + num + "位顾客");
            } else {
                System.out.println("目前没有空位,请第" + num + "位顾客等待");
            }
            position.acquire();
            System.out.println("第" + num + "位顾客进入");
            Thread.sleep(5000L);
            System.out.println("第" + num + "位顾客退出");
            position.release();

        } catch (Exception e) {

        } finally {

        }
    }


    public static void main(String args[]) {
        //无界线程池，可以进行自动线程回收
        ExecutorService list = Executors.newCachedThreadPool();
        Semaphore position = new Semaphore(5);
        for (int i = 0; i < 20; i++) {
            list.execute(new SemaphoreTest(i, position));
        }
        list.shutdown();
        try {
            position.acquire(5);
            System.out.println("所有资源回收");
            position.release(5);
        } catch (Exception e) {

        }
    }
}
